package com.ruoyi.app.common.utils;


import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.StringUtils;
import net.coobird.thumbnailator.Thumbnails;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ProductImageUtils {
    private static final String chinese = "[\u0391-\uFFE5]";
    private static String staticPath;

    static {
        String dir = System.getProperty("user.dir");
        if (System.getProperty("os.name").startsWith("Win") || System.getProperty("os.name").startsWith("win")) {
            staticPath = dir + "/ruoyi-app/src/main/resources/static/";
        } else {
            staticPath = new File(dir).getParent() + "/ruoyi-app/src/main/resources/static/";
        }
    }

    public static InputStream posterCompose(Map<String, String> params, File wxaCode) {
        try {
            BufferedImage wxaCodeImgBuffer = Thumbnails.of(wxaCode).size(175, 175).asBufferedImage();
            BufferedImage mainImgBuffer = scaleImage(new URL(params.get("main")), 420, 420);
            if (null != mainImgBuffer) {
                BufferedImage textImgBuffer = handleTextWaterMark(params.get("title"));
                BufferedImage priceBuffer = handlePriceMark(params.get("price"));
                Thumbnails.Builder builder = Thumbnails.of(new File(staticPath + params.get("bg"))).scale(1).outputQuality(1f);
                builder.watermark(PosterPosition.QR_CODE, wxaCodeImgBuffer, 1f);
                builder.watermark(PosterPosition.MAIN, mainImgBuffer, 1f);
                builder.watermark(PosterPosition.TEXT, textImgBuffer, 1f);
                builder.watermark(PosterPosition.PRICE, priceBuffer, 1f);
                if (StringUtils.isNotEmpty(params.get("skuDesc"))) {
                    BufferedImage skuBuffer = handleSkuMark("已选：" + params.get("skuDesc"));
                    builder.watermark(PosterPosition.SKU, skuBuffer, 1f);
                }
                if (StringUtils.isNotEmpty(params.get("remark"))) {
                    BufferedImage remarkBuffer = handleRemarkMark(params.get("remark"));
                    builder.watermark(PosterPosition.REMARK, remarkBuffer, 1f);
                }
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                ImageIO.write(builder.asBufferedImage(), "png", os);
                return new ByteArrayInputStream(os.toByteArray());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    private enum PosterPosition implements net.coobird.thumbnailator.geometry.Position {
        QR_CODE {
            public Point calculate(int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8) {
                int x = 425;
                int y = var2 - 295 + (150 - var4 / 2);
                return new Point(x, y);
            }
        },
        MAIN {
            public Point calculate(int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8) {
                int x = (var1 - var3) / 2;
                int y = (var2 / 2 - var4) / 2 + 80;
                if (var4 < 420) {
                    y = 170;
                }
                return new Point(x, y);
            }
        },
        TEXT {
            public Point calculate(int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8) {
                int x = 110;
                int y = 560;
                return new Point(x, y);
            }
        },
        PRICE {
            public Point calculate(int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8) {
                int x = 110;
                int y = 790;
                return new Point(x, y);
            }
        },
        REMARK {
            public Point calculate(int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8) {
                int x = 110;
                int y = 840;
                return new Point(x, y);
            }
        },
        SKU {
            public Point calculate(int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8) {
                int x = 110;
                int y = 710;
                return new Point(x, y);
            }
        }
    }

    private static BufferedImage append(int fontCount) {
        int height = 54;
        int width = (fontCount + 3) * 30;
        BufferedImage formatImage = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D graphics = formatImage.createGraphics();
        graphics.setColor(new Color(46, 94, 255));
        graphics.drawRoundRect(0, 0, width, height, height, height);
        graphics.fillRoundRect(0, 0, width, height, height, height);//涂一个圆角矩形块
        return formatImage;
    }

    private static BufferedImage circle(String url) {
        BufferedImage avatarImage;
        try {
            avatarImage = ImageIO.read(new URL(url));
            int width = 90;
            // 透明底的图片
            BufferedImage formatAvatarImage = new BufferedImage(width, width, BufferedImage.TYPE_4BYTE_ABGR);
            Graphics2D graphics = formatAvatarImage.createGraphics();
            //把图片切成一个圓

            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            //留一个像素的空白区域，这个很重要，画圆的时候把这个覆盖
            int border = 1;
            //图片是一个圆型
            Ellipse2D.Double shape = new Ellipse2D.Double(border, border, width - border * 2, width - border * 2);
            //需要保留的区域
            graphics.setClip(shape);
            graphics.drawImage(avatarImage, border, border, width - border * 2, width - border * 2, null);
            graphics.dispose();

            //在圆图外面再画一个圆
            //新创建一个graphics，这样画的圆不会有锯齿
            graphics = formatAvatarImage.createGraphics();
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            int border1 = 3;
            //画笔是4.5个像素，BasicStroke的使用可以查看下面的参考文档
            //使画笔时基本会像外延伸一定像素，具体可以自己使用的时候测试
            Stroke s = new BasicStroke(4.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
            graphics.setStroke(s);
            graphics.setColor(Color.WHITE);
            graphics.drawOval(border1, border1, width - border1 * 2, width - border1 * 2);
            graphics.dispose();
            return formatAvatarImage;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("超時請重試！");
        }
    }

    /**
     * 标题型水印
     *
     * @return java.awt.image.BufferedImage
     */
    private static BufferedImage handleTextWaterMark(String title) {
        int fontSize = 32;
        int limit = 14;
        List<String> titles = new ArrayList<>();
        final Font font = new Font("思源黑体 CN Bold", Font.PLAIN, fontSize);
        BufferedImage image = new BufferedImage(875, 350, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        image = g.getDeviceConfiguration().createCompatibleImage(925, 350, Transparency.TRANSLUCENT);
        g = image.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(new Color(0, 0, 0));
        List<int[]> indexList = getEnterIndexList(title,limit);
        for (int[] oneArr:indexList
             ) {
            titles.add(title.substring(oneArr[0],oneArr[1]));
        }
        g.setFont(font);
        for (int i = 0; i < titles.size(); i++) {
            if (0 == i) {
                g.drawString(titles.get(i), 0, fontSize);
            } else {
                g.drawString(titles.get(i), 0, Math.round(i * (15 + fontSize)) + fontSize);
            }
        }
        g.dispose();
        return image;
    }

    /**
     * 标题型水印
     *
     * @return java.awt.image.BufferedImage
     */
    private static BufferedImage handleRemarkMark(String title) {
        int fontSize = 24;
        int limit = 12;
        List<String> titles = new ArrayList<>();

        final Font font = new Font("思源黑体 CN Bold", Font.PLAIN, fontSize);
        BufferedImage image = new BufferedImage(875, 350, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        image = g.getDeviceConfiguration().createCompatibleImage(830, 350, Transparency.TRANSLUCENT);
        g = image.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(new Color(255, 0, 0));
        List<int[]> indexList = getEnterIndexList(title,limit);
        for (int[] oneArr:indexList
        ) {
            titles.add(title.substring(oneArr[0],oneArr[1]));
        }
        g.setFont(font);
        for (int i = 0; i < titles.size(); i++) {
            if (0 == i) {
                g.drawString(titles.get(i), 0, fontSize);
            } else {
                g.drawString(titles.get(i), 0, Math.round(i * (15 + fontSize)) + fontSize);
            }
        }
        g.dispose();
        return image;
    }

    /**
     * 标题型水印
     *
     * @return java.awt.image.BufferedImage
     */
    private static BufferedImage handleSkuMark(String title) {
        int fontSize = 24;
        int limit = 23;
        List<String> titles = new ArrayList<>();
        final Font font = new Font("思源黑体 CN Bold", Font.PLAIN, fontSize);
        BufferedImage image = new BufferedImage(875, 350, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        image = g.getDeviceConfiguration().createCompatibleImage(925, 100, Transparency.TRANSLUCENT);
        g = image.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(new Color(80, 80, 80));
        List<int[]> indexList = getEnterIndexList(title,limit);
        for (int[] oneArr:indexList
        ) {
            titles.add(title.substring(oneArr[0],oneArr[1]));
        }
        g.setFont(font);
        for (int i = 0; i < titles.size(); i++) {
            if (0 == i) {
                g.drawString(titles.get(i), 0, fontSize);
            } else {
                g.drawString(titles.get(i), 0, Math.round(i * (15 + fontSize)) + fontSize);
            }
        }
        g.dispose();
        return image;
    }

    /**
     * 价格水印
     *
     * @return java.awt.image.BufferedImage
     */
    private static BufferedImage handlePriceMark(String price) {
        int fontSize = 24;
        int limit = 16;
        int line = 1;
        int motCount;
        int residue;
        String omit = "";
        List<String> titles = new ArrayList<>();
        final Font font = new Font("思源黑体 CN Bold", Font.BOLD, fontSize);
        BufferedImage image = new BufferedImage(925, 350, BufferedImage.TYPE_INT_RGB);
        if (null == font) {
            return image;
        }
        Graphics2D g = image.createGraphics();
        image = g.getDeviceConfiguration().createCompatibleImage(925, 350, Transparency.TRANSLUCENT);
        g = image.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(new Color(236, 129, 49));
        if (price.length() > limit * line) {
            motCount = limit * line - 1;
            omit = "...";
        } else {
            motCount = price.length();
        }
        residue = motCount % limit;
        motCount -= residue;
        if (0 != motCount) {
            int begin = 0;
            for (int i = 0; i < motCount; i++) {
                if (0 == i % limit) {
                    titles.add(price.substring((begin++) * limit, begin * limit));
                }
            }
        }
        if (residue > 0) {
            titles.add(price.substring(motCount) + omit);
        }
        g.setFont(font);
        for (int i = 0; i < titles.size(); i++) {
            if (0 == i) {
                g.drawString(titles.get(i), 0, fontSize);
            } else {
                g.drawString(titles.get(i), 0, Math.round(i * (12 + fontSize)) + fontSize);
            }
        }
        g.dispose();
        return image;
    }

    /**
     * 压缩至指定图片尺寸保持图片不变形，多余部分裁剪掉
     *
     * @param fromUrl
     * @param width
     * @param height
     * @return
     */
    private static BufferedImage scaleImage(URL fromUrl, int width, int height) {
        try {
            Thumbnails.Builder builder;
            BufferedImage image = ImageIO.read(fromUrl);
            int imageWidth = image.getWidth();
            int imageHeight = image.getHeight();
            if (imageWidth <= width && imageWidth <= height) {
                builder = Thumbnails.of(image).outputQuality(1f).scale(1);
            } else {
                double xScale = (double) width / imageWidth;
                double yScale = (double) height / imageHeight;
                builder = Thumbnails.of(image).outputQuality(1f).scale(xScale > yScale ? xScale : yScale);
//                if ((float) width / height != (float) imageWidth / imageHeight) {
//                    double xScale = (double) width / imageWidth;
//                    double yScale = (double) height / imageHeight;
//                    if (xScale > 0 || yScale > 0) {
//                        if (xScale > yScale) {
//                            image = Thumbnails.of(localFile).scale(xScale).outputQuality(1f).asBufferedImage();
//                        } else {
//                            image = Thumbnails.of(localFile).scale(yScale).outputQuality(1f).asBufferedImage();
//                        }
//                    } else {
//                        if (imageWidth > imageHeight) {
//                            image = Thumbnails.of(localFile).height(height).outputQuality(1f).asBufferedImage();
//                        } else {
//                            image = Thumbnails.of(localFile).width(width).outputQuality(1f).asBufferedImage();
//                        }
//                    }
//                    builder = Thumbnails.of(image).sourceRegion(Positions.CENTER, width, height).size(width, height);
//                } else {
//                    double scale = (double) imageWidth / width;
//                    builder = Thumbnails.of(image).outputQuality(1f).scale(scale);
//                }
            }
            return builder.asBufferedImage();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static BufferedImage scaleLocalImage(File localFile, int width, int height) {
        try {
            Thumbnails.Builder builder;
            BufferedImage image = ImageIO.read(localFile);
            int imageWidth = image.getWidth();
            int imageHeight = image.getHeight();
            if (imageWidth <= width && imageWidth <= height) {
                builder = Thumbnails.of(image).outputQuality(1f);
            } else {
                double xScale = (double) width / imageWidth;
                double yScale = (double) height / imageHeight;
                builder = Thumbnails.of(image).outputQuality(1f).scale(xScale > yScale ? xScale : yScale);
//                if ((float) width / height != (float) imageWidth / imageHeight) {
//                    double xScale = (double) width / imageWidth;
//                    double yScale = (double) height / imageHeight;
//                    if (xScale > 0 || yScale > 0) {
//                        if (xScale > yScale) {
//                            image = Thumbnails.of(localFile).scale(xScale).outputQuality(1f).asBufferedImage();
//                        } else {
//                            image = Thumbnails.of(localFile).scale(yScale).outputQuality(1f).asBufferedImage();
//                        }
//                    } else {
//                        if (imageWidth > imageHeight) {
//                            image = Thumbnails.of(localFile).height(height).outputQuality(1f).asBufferedImage();
//                        } else {
//                            image = Thumbnails.of(localFile).width(width).outputQuality(1f).asBufferedImage();
//                        }
//                    }
//                    builder = Thumbnails.of(image).sourceRegion(Positions.CENTER, width, height).size(width, height);
//                } else {
//                    double scale = (double) imageWidth / width;
//                    builder = Thumbnails.of(image).outputQuality(1f).scale(scale);
//                }
            }
            return builder.asBufferedImage();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static int getLength(String str) {
        String strL0550 = "0123456789qwertyuiopasdfghjklzxcvbnm`~!@#$%^&*()_+/*-,.[]:;'\"?<>\\|{}";
        String strL0800 = "QWERTYUIOPASDFGHJKLZXCVBNM";
        double len = 0.000;
        for (int i = 0; i < str.length(); i++) {
            if(strL0550.contains(str.substring(i, i+1))){
                len += 0.550;
            }else if(strL0800.contains(str.substring(i, i+1))){
                len += 0.800;
            }else{
                len += 1.000;
            }
        }
        return Double.valueOf(len).intValue();
    }

    private static List<int[]> getEnterIndexList(String str,int limit){
        List<int[]> indexList = new ArrayList<>();
        int start = 0;
        int end;
        String lineStr = "";
        for(int i=0;i<str.length();i++){
            lineStr +=str.substring(i, i+1);
            if(getLength(lineStr)>=limit || i == str.length()-1){
                end = i == str.length()-1?i+1:i;
                indexList.add(new int[]{start,end});
                start = end;
                lineStr = "";
            }
        }
        return indexList;
     }
}
